import { Injectable } from "@nestjs/common"
import { AliPayEntity } from "./aliPay.entity"
import { InjectRepository } from "@nestjs/typeorm"
import { Repository } from "typeorm"
import { image } from "qr-image"
import { AliPayPayment } from "./aliPay.payment"
import { OrderEntity } from "../order/order.entity"
import { getCurrentDate } from "../../utils/getCurrentDate"
import { AuthorizationEntity } from "../authorization/authorization.entity"

@Injectable()
export class AliPayService {
  constructor(
    @InjectRepository(AliPayEntity)
    private readonly aliPayEntity: Repository<AliPayEntity>,
    private readonly aliPayment: AliPayPayment,
    @InjectRepository(OrderEntity)
    private readonly orderEntity: Repository<OrderEntity>,
    @InjectRepository(AuthorizationEntity)
    private readonly authorizationEntity: Repository<AuthorizationEntity>
  ) {}

  /**
   * Initiation payment
   * @param query
   * @param res
   */
  public async doPay(query: any, res: any): Promise<void> {
    const url = await this.aliPayment.generateUrl(query)
    // Create order data
    const { total, pid, title, order } = query
    const orderData = {
      uid: "2002052700",
      type: 0,
      status: 0,
      total,
      pid,
      title,
      order,
      create_date: getCurrentDate()
    }
    // Save order
    await this.orderEntity.save(orderData)
    console.log("aliPayUrl:", url)
    return image(url, {
      type: "png",
      size: 6,
      margin: 3,
      ec_level: "L"
    }).pipe(res)
  }

  /**
   * Obtain payment configuration
   * @param res
   */
  public async getConfig(res: any): Promise<void> {
    const data = await this.aliPayEntity.findOne({ where: { id: 1 } })
    res.json(data)
  }

  /**
   * Save payment configuration
   * @param body
   * @param res
   */
  public async saveConfig(body: any, res: any) {
    try {
      await this.aliPayEntity.save(body)
      res.json({ status: "success", message: "配置保存成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Payment callback
   * @param body
   * @description Verify the status of payment and update the status of order
   */
  public async notify(body: any): Promise<string> {
    const result = await this.aliPayment.rsaCheck(body)
    if (result && body["trade_status"] === "TRADE_SUCCESS") {
      // Update order status
      await this.orderEntity.update(
        { order: body["out_trade_no"] },
        { status: 1 }
      )
      // Query order information based on order number
      const data = await this.queryBasedOrder(body["out_trade_no"])
      // Execute authorization
      await this.authorizationEntity.save(data)
      console.log("aliPayOrder:", body["out_trade_no"]) // order number
      return "success" // Tell aliPay that it has been finished processing, and don't send any more messages
    }
  }
  /**
   * Query order information based on order number
   * @param order
   */
  private async queryBasedOrder(order: string): Promise<object> {
    const data = await this.orderEntity.findOne({ where: { order } })
    const { uid, pid, title } = data
    return {
      user_id: uid,
      app_name: title,
      app_id: pid,
      body: "example.com",
      status: 1,
      type: 0, // Domain
      create_date: getCurrentDate(),
      over_date: "2101-11-05"
    }
  }

  /**
   * Whether the payment is open
   * @param res
   */
  public async isOpen(res: any): Promise<void> {
    const result = await this.aliPayEntity.findOne({ where: { id: 1 } })
    res.json({ isOpen: result.status })
  }
}
